package com.github.binarylei.curator.lock;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 由 Zookeeper 实现的分布式锁
 * @author: leigang
 * @version: 2018-04-06
 */
public class Lock2 {

    private static final String CONNECT_ADDR = "127.0.0.1:2181";
    private static final int SEESION_OUTTIME = 5 * 1000;
    
    public static CuratorFramework createCuratorFramework() {
        //1. 重试策略：初试时间为1s，重试10次
        ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(1000, 10);

        //2. 通过工厂创建连接
        CuratorFramework cf = CuratorFrameworkFactory.builder()
                .connectString(CONNECT_ADDR)
                .sessionTimeoutMs(SEESION_OUTTIME)
                .retryPolicy(retryPolicy)
                .build();

        return cf;
    }
    
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    CuratorFramework cf = createCuratorFramework();
                    cf.start();
                    // 由 Zookeeper 实现的分布式锁
                    InterProcessMutex lock = new InterProcessMutex(cf, "/curator");
                    //ReentrantLock reentrantLock = new ReentrantLock();

                    try {
                        countDownLatch.await();
                        lock.acquire();
                        //reentrantLock.lock();
                        genarNo();
                        System.out.println(Thread.currentThread().getName() + "执行业务逻辑...");
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        try {
                            // 释放
                            lock.release();
                            //reentrantLock.unlock();
                        } catch (Exception e) {
                            ;
                        }
                    }
                }
            }).start();
        }

        Thread.sleep(1000);
        countDownLatch.countDown();
    }

    private static int count = 10;

    public static void genarNo() {
        System.out.println(--count);
    }
}
